package com.zen.lon.open.remote.metadata;

import com.zen.lon.open.remote.exp.RemoteClientException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 方法调用元数据信息
 *
 * @author ZonLen since on 2021/7/9 下午10:22
 */
@Slf4j
public class RemoteClientParamMetadata {

  private Integer requestBodyIndex;

  private final Map<String, Integer> requestParams = new HashMap<>();

  private final Map<String, Integer> pathVariables = new HashMap<>();

  public RemoteClientParamMetadata(Method method) {
    Parameter[] parameters = method.getParameters();
    if (null == parameters) {
      return;
    }
    for (int i = 0; i < parameters.length; i++) {
      if (parameters[i].isAnnotationPresent(RequestBody.class)) {
        requestBodyIndex = i;
      } else {
        final Parameter parameter = parameters[i];
        if (parameter.isAnnotationPresent(PathVariable.class)) {
          final PathVariable pathVariable = parameter.getAnnotation(PathVariable.class);
          if (StringUtils.isBlank(pathVariable.name()) && StringUtils
              .isBlank(pathVariable.value())) {
            throw new RemoteClientException(
                "请在请求函数【" + method.getName() + "】的参数注解@PathVariable('alias')添加别名");
          }
          final String name = StringUtils.isNotBlank(pathVariable.value()) ? pathVariable.value()
              : pathVariable.name();
          pathVariables.put(name, i);
        } else if (parameter.isAnnotationPresent(RequestParam.class)) {
          final RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
          if (StringUtils.isBlank(requestParam.value()) && StringUtils
              .isBlank(requestParam.name())) {
            throw new RemoteClientException(
                "请在请求函数【" + method.getName() + "】的参数注解@RequestParam('alias')注解添加别名");
          }
          final String name = StringUtils.isNotBlank(requestParam.value()) ? requestParam.value()
              : requestParam.name();
          requestParams.put(name, i);
        } else {
          throw new RemoteClientException(
              "请在请求函数【" + method.getName() + "】的参数上添加默认@RequestParam('alias')注解");
        }
      }
    }
  }

  public Map<String, Object> pathVariables(Object[] args) {
    final Map<String, Object> urlParams = new HashMap<>(pathVariables.size());
    pathVariables.forEach((name, index) -> urlParams.put(name, args[index]));
    return urlParams;
  }

  public Object requestBodyParam(Object[] args) {
    if (null != requestBodyIndex) {
      return args[requestBodyIndex];
    }
    return null;
  }

  public String requestParams(Object[] args, String url) {
    final StringBuilder path = new StringBuilder(url);
    final AtomicBoolean isPass = new AtomicBoolean(url.contains("?"));
    requestParams.forEach((name, index) -> {
      if (isPass.get()) {
        path.append("&").append(name).append("=").append(args[index]);
      } else {
        isPass.set(true);
        path.append("?").append(name).append("=").append(args[index]);
      }
    });
    return path.toString();
  }
}
